import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_shopper/models/cart_model.dart';
import 'package:provider_shopper/models/catalog_model.dart';
import 'package:provider_shopper/screens/my_cart.dart';

class MyCatalog extends StatelessWidget {
  static const myCatalogKey = '/catalog';
  const MyCatalog({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        // A sliver is a widget backed by a [RenderSliver] subclass, i.e. one that implements the constraint/geometry protocol that uses [SliverConstraints] and [SliverGeometry].
        slivers: [
          // SliverAppBar
          _MyAppBar(),
          // Creates a sliver that contains a single box widget.
          SliverToBoxAdapter(
            // 此处，为了能够看到SizedBox的效果，将SizedBox替换为Container并添加颜色
            child: Container(
              height: 12,
              decoration: BoxDecoration(color: Colors.grey),
            ),
          ),
          // Creates a sliver that places box children in a linear array.
          SliverList(
            // The delegate that provides the children for this widget.
            // The children are constructed lazily using this delegate to avoid creating more children than are visible through the [Viewport].
            delegate: SliverChildBuilderDelegate(
              (context, index) => _MyListItem(index: index),
            ),
          ),
        ],
      ),
    );
  }
}

class _MyAppBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SliverAppBar(
      title: Text('Catalog', style: Theme.of(context).textTheme.headlineLarge),
      floating: true,
      actions: [
        IconButton(
          onPressed: () => Navigator.pushNamed(context, MyCart.myCartKey),
          icon: Icon(Icons.shopping_cart),
        ),
      ],
    );
  }
}

class _MyListItem extends StatelessWidget {
  final int index;
  const _MyListItem({required this.index});

  @override
  Widget build(BuildContext context) {
    // R select<T, R>(R Function(T) selector)
    //
    // Watch a value of type [T] exposed from a provider, and mark this widget for rebuild on changes of that value.
    var item = context.select<CatalogModel, Item>(
      (catalog) => catalog.getByPosition(index),
    );

    var textTheme = Theme.of(context).textTheme.headlineSmall;
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      // Creates a box that limits its size only when it's unconstrained.
      //
      // The [maxWidth] and [maxHeight] arguments must not be negative.
      //
      // The [LimitedBox] widget limits its size only when it's unconstrainced. This can be useful in scenarios where the widget is placed in an unbounded environment, such as  a list.
      //
      // The [LimitedBox] widget will limit the size of its child only when the maximum width or height is unconstrained.
      child: LimitedBox(
        maxHeight: 48,
        child: Row(
          children: [
            AspectRatio(aspectRatio: 1, child: Container(color: item.color)),
            SizedBox(width: 24),
            Expanded(child: Text(item.name, style: textTheme)),
            SizedBox(width: 24),
            _AddButton(item: item),
          ],
        ),
      ),
    );
  }
}

class _AddButton extends StatelessWidget {
  final Item item;
  const _AddButton({required this.item});

  @override
  Widget build(BuildContext context) {
    // context.select()函数用于监听model的部分值。
    // 定义一个函数用于选择（也就是返回）model中被关注到的部分，但model中的这部分之发生变化时，provider package就重绘widget
    // 
    // 这种操作可以显著改善执行性能
    var isInCart = context.select<CartModel, bool>(
      (cart) => cart.items.contains(item),
    );
    return TextButton(
      onPressed: isInCart
          ? null
          : () {
              var cart = context.read<CartModel>();
              cart.add(item);
            },
      style: ButtonStyle(
        overlayColor: WidgetStateProperty.resolveWith<Color?>((states) {
          if (states.contains(WidgetState.pressed)) {
            return Theme.of(context).primaryColor;
          }
          return null;
        }),
      ),
      child: isInCart ? Icon(Icons.check, semanticLabel: 'ADDED') : Text('ADD'),
    );
  }
}
